//============================================================================
// Name        : SocketClientMain.cpp.cpp
// Author      : Ge LIang
// Version     :
// Copyright   : @2016 GeLiang
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
using namespace std;

#include "common.h"
#include "GWSocketClient.h"
#include "GWSocketHandler.h"
#include <stdlib.h>
#include <string.h>
#include "SocketLooper.h"

SocketLooper::SocketLooper(const char* host, int port, int timeoutInSecond,
		int loopTag) {
	isStop = false;
	isLooping = false;
	handlePacketImp = NULL;
	handleSocketClosedImp = NULL;
	looperTag = loopTag;
	GWSocketHandler* handler = new GWSocketHandler(0, 4);
	client = new GWSocketClient(handler, host, port, timeoutInSecond);
	mTimeout = timeoutInSecond * 1000;
}
SocketLooper::~SocketLooper() {
	stopLoop();
}

void SocketLooper::startLoop() {
	if (isLooping) {
		LOGE("had Loop");
		return;
	}
	isLooping = true;
//
//	#if defined(_WIN32)
//	unsigned long nThreadId = 0;
//	thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)StaticRun, this, 0, &nThreadId);
//	#else
//	pthread_create(&thread, NULL, StaticRun, (void*) this);
//	#endif
	this->start();
}
void SocketLooper::stopLoop() {
	if (!isStop) {
//	#if defined(_WIN32)
//		if (thread != 0) {
//			WaitForSingleObject(thread, INFINITE);
//			CloseHandle(thread);
//			thread = 0;
//		}
//	#else
//		pthread_join(thread,0);
//	#endif
		isStop = true;
		LOGE("join");
		this->join();
		LOGE("join exit");
	}

	Packet *packet = NULL;
	while ((packet = sendQueue.pop()) != NULL) {
		free(packet);
	}
}


void SocketLooper::setRecvHandler(handlePacket handler,
		handleSocketClosed handler1) {
	if (handler == null || handler1 == null) {
		LOGE("handler is null");
		return;
	}
	handlePacketImp = handler;
	handleSocketClosedImp = handler1;
}

int SocketLooper::putToSend(char* data, int size) {
	if (isLooping) {
		if (data == null || size > BUF_MAX_SIZE || size <= 0) {
			return ERR_OUT_BUF_SIZE;
		}
		Packet* packet = (Packet*) malloc(sizeof(Packet));
		if (packet == null) {
			return ERR_OOM;
		}
		memset(packet, 0, sizeof(Packet));
		memcpy(packet->data, data, size);
		packet->size = size;
		sendQueue.push(packet);
		return 0;
	} else {
		LOGW("put fail,loop had exit");
		return ERR_DIS_CONNECT_SOCKET;
	}
}

void SocketLooper::loop() {
	int notRecvDataTime = 0;
	long long lastTime = systemCurrentTime();
	while (true) {
		long long ex = systemCurrentTime() - lastTime;
		if (ex > mTimeout / 2) {
			client->heartbeat();
			lastTime = systemCurrentTime();
		}
		Packet *packet = NULL;
		int sendByteSize = 0;
		while ((packet = sendQueue.pop()) != NULL) {
			sendByteSize = client->send(packet->data, packet->size);
			free(packet);
			if (sendByteSize < 0) {
				LOGW("send Fail %d", sendByteSize);
				break; //break sendQueue.pop() while
			}
		}
		if (sendByteSize < 0) {
			break; //break loop()
		}
		int recvByteLen = 0;
		if (handlePacketImp != null) {
			recvByteLen = client->recv(handlePacketImp);
//			recvByteLen =0;
		}
		if (recvByteLen <= 0) {
			threadSleep(LOOP_INTERVALS);
//			threadSleep(0);
			notRecvDataTime += LOOP_INTERVALS;
			if (notRecvDataTime > mTimeout) {
				LOGW("xxxx  timeout  xxxx");
				break;
			} else if (isStop) {
				//TODO stop after send all msg
				LOGI("xxxx  isStop xxxx");
				break;
			}
		} else {
//			LOGI("+++ recv %d +++",recvByteLen);
			notRecvDataTime = 0; //reset ;
		}
	}


	if (client != NULL) {
		if (((SocketClient*) client)->mSocketHandler != NULL) {
			delete (((SocketClient*) client)->mSocketHandler);
		}
		delete (SocketClient*) client;
		client = NULL;
	}
	isLooping = false;
	isStop = true;
	if (handleSocketClosedImp != null) {
//		handleSocketClosedImp(looperTag);
	}
	LOGI("xxxx  thread exit xxxx");
}

